#include <iostream>
#include <vector>
#include <unistd.h>
#include <assert.h>
#include <sys/wait.h>
#include "Task.hpp"
const int num = 5; //为什么不用宏呢
static int number = 1;
struct channel
{
    int ctrlfd;  //写端 fd
    pid_t workerid;  //读端子进程
    std::string name;

    channel(int fd, pid_t id)
        :ctrlfd(fd)
        ,workerid(id)
    {
        name = "channel" + std::to_string(number++);
    }
};

void Work()
{
    while(true)
    {
        int code = 0;
        ssize_t n = read(0, &code, sizeof code);
        if(n == sizeof(code)) //这里用assert就不合理了
        {
            if(!init.CheckCode(code))
                continue;
            init.RunTask(code);
        }
        else if(n == 0) //那要是没有向里面发消息呢？
        {
            break;
        }
        else{}
    }
    // std::cout << "child quit" << std::endl; ///源代码中下一行就是exit
}
void CreateChannels(std::vector<channel>& channels)
{
    //记录待删除写端fd
    std::vector<int> releasefd;
    for(int i = 0; i < num; i++)
    {
        //1.创建管道
        int pipefd[2];
        if(pipe(pipefd) == -1)
        {
            perror("pipe");
            return;
        }
        
        //2.创建子进程
        pid_t id = fork();
        assert(id != -1);   //assert与 if什么时候用

        //3.构建单项通信信道
        if(id == 0)
        {
            //释放fd
            if(!releasefd.empty())
                for(auto fd : releasefd)
                    close(fd);

            close(pipefd[1]);
            dup2(pipefd[0], 0); ///pipefd[0]值就是3
            Work();
            std::cout << getpid() << " quit" << std::endl;
            exit(0);
        }

        close(pipefd[0]);
        channels.push_back(channel(pipefd[1], id));
        //添加fd
        releasefd.push_back(pipefd[1]);
    }
}
void SendCommand(std::vector<channel>& channels, int num = -1)
{
    int pos = 0;
    while(true)
    {
        //1.随机选择一个任务
        int command = init.SelectTask();
        
        //2.选择一个信道
        const channel& channel = channels[pos++];
        pos %= channels.size();

        //3.写入管道
        write(channel.ctrlfd, &command, sizeof command);

        //4.判断退出
        if(--num == 0)
            break;

        sleep(1);
    }
}

void ReleaseChannels(std::vector<channel>& channels)
{
    // 方法1
    for(const auto& channel : channels)
    {
        close(channel.ctrlfd);   //因为只有当最后一个进程退出的时候，向前所有进程一个个退出
        waitpid(channel.workerid, nullptr, WNOHANG);
        sleep(1);
    }
    // for(const auto& channel : channels)
    // {
        
    //     pid_t rid = waitpid(channel.workerid, nullptr , 0);
    //     if(rid == channel.workerid)
    //         std::cout << channel.workerid << " wait success" << std::endl;
    // }
    //方法2
    // for(int i = channels.size() - 1; i >= 0; i--)
    // {
    //     close(channels[i].ctrlfd);
    //     waitpid(channels[i].workerid, nullptr, 0);
    //     sleep(1);
    // }
}
int main()
{
    std::vector<channel> channels;
    //1. 创建信道、子进程
    CreateChannels(channels);
    //2. 分配任务
    SendCommand(channels, 5);
    //3. 回收
    ReleaseChannels(channels);
    return 0;
}